/*
 * mibTreeModel.cpp
 *
 *  Created on: 2011-7-7
 *      Author: fufan
 */
#include "mibTreeModel.h"


MibTreeModel::MibTreeModel(QObject *parent)
									:QAbstractItemModel(parent)
{
			QList<QVariant> title;
			root = new MibItem(title);
			setupModel();
}

MibTreeModel::~MibTreeModel()
{
			delete root;
}

QModelIndex MibTreeModel::parent(const QModelIndex &index)const
{
			if(!index.isValid())
			{
				return QModelIndex();
			}
			MibItem *current = static_cast<MibItem*>(index.internalPointer());
			MibItem *parentItem = current->parent();
			if(parentItem == root)
			{
							return QModelIndex();
			}
		return createIndex(parentItem->row(), 0, parentItem);
}

int MibTreeModel::rowCount(const QModelIndex &parent) const
{
			if(parent.column() > 0)
				return 0;
			MibItem *parentItem;
			if(!parent.isValid())
			{
				parentItem = root;
			}
			else
			{
				parentItem = static_cast<MibItem*>(parent.internalPointer());
			}
			return parentItem->childCount();
}


int MibTreeModel::columnCount(const QModelIndex &parent) const
{
			return 1;
}

QVariant MibTreeModel::data(const QModelIndex &index, int role) const
{
		if(!index.isValid())
		{
			return QVariant();
		}
		MibItem *item = static_cast<MibItem *>(index.internalPointer());
		if(role == Qt::DecorationRole)
		{
			return returnIconByKind(item);
		}
		if(role != Qt::DisplayRole)
		{
			return QVariant();
		}
		return item->dataValue(index.column());
}

QVariant MibTreeModel::headerData(int section, Qt::Orientation orientation,
																							int role) const
{
		return QVariant();
}

QModelIndex MibTreeModel::index(int row, int column, const QModelIndex &parent)const
{
			if(!hasIndex(row, column, parent))
			{
				return QModelIndex();
			}
			MibItem *parentItem;
			if(!parent.isValid())
			{
				parentItem = root;
			}
			else
			{
				parentItem = static_cast<MibItem *>(parent.internalPointer());
			}

			MibItem *child = parentItem->child(row);
			if(child)
				return createIndex(row, column, child);
			else
				return QModelIndex();
}


void MibTreeModel::setupModel()
{
			QList<QVariant> mibData;
			mibData << "MIB Tree" << "" << "" << "" << "" << "" << "" << "";
			MibItem *MibTree = new MibItem(mibData,root);
			root->appendChild(MibTree);

			QList<QVariant> isoData;
			isoData << "iso" << "1" << "" << "" << "" << "" << "" << "";
			MibItem *iso = new MibItem(isoData, MibTree);
			MibTree->appendChild(iso);

			SmiNode *smiNode;
			SmiModule *smiModule;
			int i;
			const char *module[]= {"./mibs/RFC1213-MIB", "./mibs/RFC1155-SMI", "./mibs/RFC-1212"};
			for(i=0; i<3; i++)
			{
				if(!smiLoadModule(module[i]))
				{
					printError("加载MIB文件出错！");
					break;
				}
			}
			smiModule = smiGetModule(module[1]);
			smiNode = smiGetFirstNode(smiModule, SMI_NODEKIND_ANY);
			if(smiNode != NULL)
			{
				QList<QVariant> orgData;
				orgData = getDatafromNode(smiNode);
				MibItem *org = new MibItem(orgData, iso);
				iso->appendChild(org);

				readMibNode(smiNode, org);
			}
			else
			{
				printError("无法找到第一个节点！");
			}
			smiExit();
}

//递归地读取mib文件中的节点，形成树形结构, 深度优先遍历
void MibTreeModel::readMibNode(SmiNode *parentNode, MibItem *parentItem)
{

	SmiNode *smiNode;
	for((smiNode=smiGetFirstChildNode(parentNode)); smiNode; smiNode=smiGetNextChildNode(smiNode))
	{
		QList<QVariant> data;
		data = getDatafromNode(smiNode);
		MibItem *item = new MibItem(data, parentItem);
		parentItem->appendChild(item);
		readMibNode(smiNode, item);

	}
}

//从节点中获取信息
QList<QVariant> MibTreeModel::getDatafromNode(SmiNode *smiNode) const
{
			QList<QVariant> data;
			QString name;
			QString oid;
			QString access;
			QString status;
			QString type;
			QString baseType;
			QString kind;
			QString description;

			if(!smiNode)
			{
				return data;
			}

			if(smiNode->name)
			{
				name = smiNode->name;
			}
			if(smiNode->oidlen > 0)
			{
				string oidStr;

				int len = smiNode->oidlen;

				for(int i=0; i < len; i++)
				{
					char ch[10];
					int k=0;
					//将整数转化为字符串
					for(int j=*(smiNode->oid+i); j>0&&k<10; j/=10, k++)
					{
							ch[k] = j%10 + '0';
					}
					ch[k] = '\0';
					//反转字符串
					char temp;
					for(int l=0; l<k/2; l++)
					{
						temp = ch[l];
						ch[l] = ch[k-1-l];
						ch[k-1-l] = temp;
					}

					string value(ch);

					oidStr += value;
					if(i != len-1)
						oidStr += ".";
				}
				oid = oidStr.c_str();
			}

			access = getAccess(smiNode->access);
			status = getStatus(smiNode->status);

			SmiType *smiType = smiGetNodeType(smiNode);
			if(smiType)
			{
				type = smiType->name;
				baseType = getBaseType(smiType->basetype);
			}

			kind = getKind(smiNode->nodekind);

			if(smiNode->description)
			{
				description = smiNode->description;
			}

			data << name << oid << access << status << type << baseType << kind << description;
			return data;
}

const char* MibTreeModel::getAccess(SmiAccess access) const
{
	switch(access)
	{
	case SMI_ACCESS_UNKNOWN:
		return "";
	case SMI_ACCESS_NOT_IMPLEMENTED:
		return "not-implemented";
	case  SMI_ACCESS_NOT_ACCESSIBLE:
		return "not-accessible";
	case SMI_ACCESS_NOTIFY:
		return "notify";
	case SMI_ACCESS_READ_ONLY:
		return "read-only";
	case SMI_ACCESS_READ_WRITE:
		return "read-write";
	case SMI_ACCESS_INSTALL:
		return "install";
	case SMI_ACCESS_INSTALL_NOTIFY:
		return "install-notify";
	case SMI_ACCESS_REPORT_ONLY:
		return "report-only";
	case SMI_ACCESS_EVENT_ONLY:
		return "event-only";
	}
	return "";
}

const char* MibTreeModel::getStatus(SmiStatus status) const
{
	switch(status)
	{
	case SMI_STATUS_UNKNOWN:
		return "";
	case SMI_STATUS_CURRENT:
		return "current";
	case SMI_STATUS_DEPRECATED:
		return "deprecated";
	case SMI_STATUS_MANDATORY:
		return "mandatory";
	case SMI_STATUS_OPTIONAL:
		return "optional";
	case SMI_STATUS_OBSOLETE:
		return "obsolete";
	}
	return "";
}

const char* MibTreeModel::getBaseType(SmiBasetype baseType) const
{
	switch(baseType)
	{
	case SMI_BASETYPE_UNKNOWN:
		return "";
	case SMI_BASETYPE_INTEGER32:
		return "integer32";
	case 	SMI_BASETYPE_OCTETSTRING:
		return "octetstring";
	case SMI_BASETYPE_OBJECTIDENTIFIER:
		return "objectIdentifier";
	case SMI_BASETYPE_UNSIGNED32:
		return "unsigned32";
	case SMI_BASETYPE_INTEGER64:
		return "integer64";
	case SMI_BASETYPE_UNSIGNED64:
		return "unsigned64";
	case SMI_BASETYPE_FLOAT32:
		return "float32";
	case SMI_BASETYPE_FLOAT64:
		return "float64";
	case SMI_BASETYPE_FLOAT128:
		return "float128";
	case SMI_BASETYPE_ENUM:
		return "enum";
	case SMI_BASETYPE_BITS:
		return "bits";
	case SMI_BASETYPE_POINTER:
		return "pointer";
	}
	return "";
}

const char* MibTreeModel::getKind(SmiNodekind kind) const
{
	switch(kind)
	{
	case SMI_NODEKIND_UNKNOWN:
		return "";
	case SMI_NODEKIND_NODE:
		return "node";
	case SMI_NODEKIND_SCALAR:
		return "scalar";
	case SMI_NODEKIND_TABLE:
		return "table";
	case SMI_NODEKIND_ROW:
		return "row";
	case SMI_NODEKIND_COLUMN:
		return "column";
	case SMI_NODEKIND_NOTIFICATION:
		return "notification";
	case SMI_NODEKIND_GROUP:
		return "group";
	case SMI_NODEKIND_COMPLIANCE:
		return "compliance";
	case SMI_NODEKIND_CAPABILITIES:
		return "capabilities";
	case SMI_NODEKIND_ANY:
		return "any";
	}
	return "";
}

QIcon MibTreeModel::returnIconByKind(MibItem *node) const
{
	  QString kind = node->dataValue(6).toString();
		if(kind == "node")
		{
			return QIcon("images/folder_yellow.png");
		}
		else if(kind == "scalar")
		{
			return QIcon("images/scalar.png");
		}
		else if(kind == "table")
		{
			return QIcon("images/folder_blue.png");
		}
		else if(kind == "row")
		{
			return QIcon("images/folder_red.png");
		}
		else if(kind == "column")
		{
			return QIcon("images/column_item.png");
		}
		else if(kind == "notification")
		{
			return QIcon("images/notification.png");
		}
		else if(kind == "group.png")
		{
			return QIcon("images/group.png");
		}
		else if(kind == "compliance")
		{
			return QIcon("images/compliance.png");
		}
		else
		{
			return QIcon("images/folder_yellow.png");
		}
}

void MibTreeModel::printError(const QString& error)
{
				QMessageBox msg;
				msg.setText(error);
				msg.exec();
}




